package com.morningstar.flow.flowable.listener;

import cn.hutool.extra.spring.SpringUtil;
import com.morningstar.common.message.FlowTaskTodoMessage;
import com.morningstar.common.message.MessageMqSender;
import com.morningstar.flow.service.FlowInstanceService;
import com.morningstar.flow.service.FlowNodeInstanceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.event.FlowableEntityEventImpl;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.impl.FlowableActivityEventImpl;
import org.flowable.engine.delegate.event.impl.FlowableProcessTerminatedEventImpl;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;

import static com.morningstar.flow.flowable.constants.VariableName.LOOP_COUNTER;

/**
 * 流程监听器
 */
@Slf4j
public class FlowProcessEventListener implements FlowableEventListener {

    @Override
    public void onEvent(FlowableEvent event) {
        // todo 策略模式
        // 节点开始了
        if (event.getType() == FlowableEngineEventType.ACTIVITY_STARTED) {
            FlowableActivityEventImpl flowableActivityEvent = (FlowableActivityEventImpl) event;
            log.info("ACTIVITY_STARTED {} {}", flowableActivityEvent.getActivityName(), flowableActivityEvent.getActivityId());
            RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class);
            Object loopCounter = runtimeService.getVariable(flowableActivityEvent.getExecutionId(), LOOP_COUNTER);
            if (StringUtils.equalsIgnoreCase(flowableActivityEvent.getActivityType(), "UserTask")
                    && loopCounter != null
                    && loopCounter.toString().equals("0")) {
                FlowNodeInstanceService flowNodeInstanceService = SpringUtil.getBean(FlowNodeInstanceService.class);
                flowNodeInstanceService.create(flowableActivityEvent);
            }
            if (StringUtils.equalsIgnoreCase(flowableActivityEvent.getActivityType(), "StartEvent") ||
                    StringUtils.equalsIgnoreCase(flowableActivityEvent.getActivityType(), "EndEvent")) {
                FlowNodeInstanceService flowNodeInstanceService = SpringUtil.getBean(FlowNodeInstanceService.class);
                flowNodeInstanceService.create(flowableActivityEvent);
            }
        }

        // 节点结束了
        if (event.getType() == FlowableEngineEventType.ACTIVITY_COMPLETED) {
            FlowableActivityEventImpl flowableActivityEvent = (FlowableActivityEventImpl) event;
            log.info("ACTIVITY_COMPLETED {} {}", flowableActivityEvent.getActivityName(), flowableActivityEvent.getActivityId());
            FlowNodeInstanceService flowNodeInstanceService = SpringUtil.getBean(FlowNodeInstanceService.class);
            flowNodeInstanceService.end(flowableActivityEvent);
        }

        // 任务创建了
        if (event.getType() == FlowableEngineEventType.TASK_CREATED) {
            FlowableEntityEventImpl flowableEntityEvent = (FlowableEntityEventImpl) event;
            TaskEntity taskEntity = (TaskEntity) flowableEntityEvent.getEntity();
            log.info("TASK_CREATED {} {} {}", taskEntity.getTaskDefinitionKey(), taskEntity.getId(), taskEntity.getAssignee());
            MessageMqSender messageMqSender = SpringUtil.getBean(MessageMqSender.class);
            // TODO 消息
            FlowTaskTodoMessage message = new FlowTaskTodoMessage("待办任务", Long.valueOf(taskEntity.getAssignee()))
                    .setFlowName("FlowName")
                    .setFlowTaskName(taskEntity.getName());
            messageMqSender.send(message);
        }

        // 流程结束了
        if (event.getType() == FlowableEngineEventType.PROCESS_COMPLETED
                || event.getType() == FlowableEngineEventType.PROCESS_COMPLETED_WITH_TERMINATE_END_EVENT) {
            FlowableProcessTerminatedEventImpl terminatedEvent = (FlowableProcessTerminatedEventImpl) event;
            log.info("PROCESS_COMPLETED {}", terminatedEvent.getProcessInstanceId());
            FlowInstanceService flowInstanceService = SpringUtil.getBean(FlowInstanceService.class);
            flowInstanceService.end(terminatedEvent);
        }
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }
}
